classdef ModelStaticAnalysisService < handle
    % MODELSTATICANALYSISSERVICE 模型静态分析服务
    % 基于DO-178规则第4条（架构分离原则）设计
    % 负责协调所有模型静态分析相关的业务逻辑
    %
    % 功能：
    %   - 模型标准检查（Model Advisor - checkModelStds）
    %   - 模型指标计算（computeModelMetrics）
    %   - 检查清单管理（createChecklist）
    %   - SDD报告生成（genSDD）
    %   - Model Advisor配置管理（setDefaultMdlAdvCfg, resetDefaultMdlAdvCfg）
    %
    % 设计原则：
    %   - 单一职责：只负责模型静态分析业务逻辑协调
    %   - 依赖注入：依赖现有的工具函数
    %   - 错误明确：遵循规则第2条，不使用silent fallback
    %   - 可测试：所有公共方法都可以独立测试
    %
    % 使用示例：
    %   % 获取单例实例（DEV环境）
    %   service = ModelStaticAnalysisService.getInstance();
    %   
    %   % 获取单例实例（CI环境）
    %   service = ModelStaticAnalysisService.getInstance('Environment', 'CI');
    %   
    %   % 模型标准检查
    %   result = service.checkStandards('MyModel');
    %   
    %   % 计算模型指标
    %   result = service.computeMetrics('MyModel');
    %   
    %   % 创建检查清单
    %   result = service.createChecklist('MyModel', 'model review checklist');
    %   
    %   % 生成SDD报告
    %   result = service.generateSDD('MyModel', 'AuthorName');
    %
    % 作者: MBD Platform Team
    % 日期: 2025-10-26
    % 遵循DO-178标准
    
    properties (Access = private)
        projectRoot         % 项目根目录
        environment         % 运行环境：'DEV' 或 'CI'
        logger              % LoggingService实例
    end
    
    methods (Access = private)
        function obj = ModelStaticAnalysisService(varargin)
            % 私有构造函数 - 初始化服务（单例模式）
            % 输入：
            %   'Environment' - 可选，运行环境 'DEV'（默认）或 'CI'
            % 基于规则第2条：不使用silent fallback，明确报告错误
            
            % 初始化日志服务
            try
                obj.logger = LoggingService.getInstance();
            catch ME
                warning('LoggingService:Unavailable', '日志服务不可用: %s', ME.message);
                obj.logger = [];
            end
            
            % 解析输入参数
            p = inputParser;
            addParameter(p, 'Environment', 'DEV', @(x) ismember(x, {'DEV', 'CI'}));
            parse(p, varargin{:});
            
            obj.environment = p.Results.Environment;
            
            try
                % 获取项目根目录
                obj.projectRoot = pwd;
                fprintf('✅ ModelStaticAnalysisService已初始化\n');
                fprintf('   项目根目录: %s\n', obj.projectRoot);
                fprintf('   运行环境: %s\n', obj.environment);
                
                if ~isempty(obj.logger)
                    obj.logger.logInfo(sprintf('ModelStaticAnalysisService已初始化 (环境: %s)', obj.environment));
                end
            catch ME
                if ~isempty(obj.logger)
                    obj.logger.logError(sprintf('模型静态分析服务初始化失败: %s', ME.message));
                end
                error('ModelStaticAnalysisService:InitFailed', ...
                    '无法初始化模型静态分析服务：%s', ME.message);
            end
        end
    end
    
    methods (Static, Access = public)
        function obj = getInstance(varargin)
            % 获取ModelStaticAnalysisService的单例实例
            % 输入：
            %   'Environment' - 可选，运行环境 'DEV'（默认）或 'CI'
            % 输出：
            %   obj - ModelStaticAnalysisService单例实例
            
            persistent instance;
            
            if isempty(instance) || ~isvalid(instance)
                instance = ModelStaticAnalysisService(varargin{:});
                fprintf('✅ 创建ModelStaticAnalysisService单例实例\n');
            end
            
            obj = instance;
        end
    end
    
    methods (Access = public)
        
        %% ==================== 模型标准检查 ====================
        
        function result = checkStandards(obj, modelName)
            % 检查模型是否符合建模标准（Model Advisor）
            % 输入：
            %   modelName - 模型名称
            % 输出：
            %   result - 包含成功标志和消息的结构体
            % 基于规则第2条：明确报告错误
            
            result = struct('success', false, 'message', '', 'reportPath', '', 'details', struct());
            
            if nargin < 2 || isempty(modelName)
                error('ModelStaticAnalysisService:InvalidInput', '模型名称不能为空');
            end
            
            if ~isempty(obj.logger)
                obj.logger.logInfo(sprintf('开始检查模型标准: %s', modelName));
            end
            
            try
                fprintf('🔍 正在检查模型标准: %s\n', modelName);
                
                % 基于规则第4条：调用独立的模型标准检查工具函数
                % 根据环境添加CI参数
                if strcmpi(obj.environment, 'CI')
                    stdResult = checkModelStds(modelName, [], 'CI');
                else
                    stdResult = checkModelStds(modelName);
                end
                
                result.success = true;
                result.message = stdResult.Message;
                result.details = stdResult;
                result.reportPath = obj.getModelStandardsReportPath(modelName);
                
                fprintf('✅ 模型标准检查完成\n');
                if ~isempty(obj.logger)
                    obj.logger.logInfo(sprintf('模型标准检查完成: %s', modelName));
                end
                
            catch ME
                result.success = false;
                result.message = sprintf('模型标准检查失败: %s', ME.message);
                result.error = ME;
                if ~isempty(obj.logger)
                    obj.logger.logError(sprintf('模型标准检查失败 [%s]: %s', modelName, ME.message));
                end
                % 使用格式化字符串避免result.message中的路径反斜杠被解释为转义字符
                error('ModelStaticAnalysisService:CheckStandardsFailed', '%s', result.message);
            end
        end
        
        %% ==================== 模型指标计算 ====================
        
        function result = computeMetrics(obj, modelName, varargin)
            % 计算模型的度量指标
            % 输入：
            %   modelName - 模型名称
            %   varargin - 可选参数：'TreatAsTopMdl'
            % 输出：
            %   result - 包含成功标志、消息和指标的结构体
            
            result = struct('success', false, 'message', '', 'reportPath', '', 'details', struct());
            
            if nargin < 2 || isempty(modelName)
                error('ModelStaticAnalysisService:InvalidInput', '模型名称不能为空');
            end
            
            if ~isempty(obj.logger)
                obj.logger.logInfo(sprintf('开始计算模型指标: %s', modelName));
            end
            
            try
                fprintf('📊 正在计算模型指标: %s\n', modelName);
                
                % 基于规则第4条：调用独立的模型指标计算工具函数
                metricsResult = computeModelMetrics(modelName, varargin{:});
                
                result.success = true;
                result.message = metricsResult.Message;
                result.details = metricsResult;
                result.reportPath = obj.getModelMetricsReportPath(modelName);
                
                fprintf('✅ 模型指标计算完成\n');
                if ~isempty(obj.logger)
                    obj.logger.logInfo(sprintf('模型指标计算完成: %s', modelName));
                end
                
            catch ME
                result.success = false;
                result.message = sprintf('模型指标计算失败: %s', ME.message);
                result.error = ME;
                if ~isempty(obj.logger)
                    obj.logger.logError(sprintf('模型指标计算失败 [%s]: %s', modelName, ME.message));
                end
                % 使用格式化字符串避免result.message中的路径反斜杠被解释为转义字符
                error('ModelStaticAnalysisService:ComputeMetricsFailed', '%s', result.message);
            end
        end
        
        %% ==================== 检查清单管理 ====================
        
        function result = createChecklist(obj, modelName, checklistType, openExisting)
            % 创建或打开检查清单
            % 输入：
            %   modelName - 模型名称
            %   checklistType - 检查清单类型
            %   openExisting - (可选) 是否为打开现有文件模式
            % 输出：
            %   result - 包含成功标志和消息的结构体
            
            result = struct('success', false, 'message', '');
            
            if nargin < 3 || isempty(modelName) || isempty(checklistType)
                error('ModelStaticAnalysisService:InvalidInput', '模型名称和检查清单类型不能为空');
            end
            
            if nargin < 4
                openExisting = false;
            end
            
            try
                fprintf('📋 正在处理检查清单: %s - %s\n', modelName, checklistType);
                
                % 基于规则第4条：调用独立的检查清单创建工具函数
                checklistResult = createChecklist(modelName, checklistType, openExisting);
                
                result.success = true;
                result.message = checklistResult.Message;
                
                fprintf('✅ 检查清单处理完成\n');
                
            catch ME
                result.success = false;
                result.message = sprintf('检查清单处理失败: %s', ME.message);
                result.error = ME;
                % 使用格式化字符串避免result.message中的路径反斜杠被解释为转义字符
                error('ModelStaticAnalysisService:CreateChecklistFailed', '%s', result.message);
            end
        end
        
        %% ==================== 设计错误检测 ====================
        
        function result = detectDesignErrors(obj, modelName, detectActiveLogic, maxProcessTime)
            % 检测模型中的设计错误或死逻辑（Design Verifier）
            % 输入：
            %   modelName - 模型名称
            %   detectActiveLogic - (可选) 'DetectActiveLogic' 或空
            %   maxProcessTime - (可选) 最大处理时间（秒）
            % 输出：
            %   result - 包含成功标志和消息的结构体
            % 基于规则第2条：明确报告错误
            
            result = struct('success', false, 'message', '', 'reportPath', '', 'details', struct());
            
            if nargin < 2 || isempty(modelName)
                error('ModelStaticAnalysisService:InvalidInput', '模型名称不能为空');
            end
            
            % 处理可选参数
            if nargin < 3
                detectActiveLogic = [];
            end
            if nargin < 4
                maxProcessTime = [];
            end
            
            try
                fprintf('🔍 正在检测设计错误: %s\n', modelName);
                
                % 基于规则第4条：调用独立的设计错误检测工具函数
                % 根据环境添加CI参数
                if strcmpi(obj.environment, 'CI')
                    designErrResult = detectDesignErrs(modelName, detectActiveLogic, maxProcessTime, 'CI');
                else
                    designErrResult = detectDesignErrs(modelName, detectActiveLogic, maxProcessTime);
                end
                
                result.success = true;
                result.message = designErrResult.Message;
                result.reportPath = obj.getDesignErrorReportPath(modelName);
                
                % 保存详细结果（CI环境）
                if strcmpi(obj.environment, 'CI')
                    result.details = designErrResult;
                end
                
                fprintf('✅ 设计错误检测完成\n');
                
            catch ME
                result.success = false;
                result.message = sprintf('设计错误检测失败: %s', ME.message);
                result.error = ME;
                % 使用格式化字符串避免result.message中的路径反斜杠被解释为转义字符
                error('ModelStaticAnalysisService:DetectDesignErrorsFailed', '%s', result.message);
            end
        end
        
        %% ==================== SDD报告生成 ====================
        
        function result = generateSDD(obj, modelName, authorNames)
            % 生成系统设计描述（SDD）报告
            % 输入：
            %   modelName - 模型名称
            %   authorNames - (可选) 作者姓名
            % 输出：
            %   result - 包含成功标志和消息的结构体
            
            result = struct('success', false, 'message', '', 'reportPath', '');
            
            if nargin < 2 || isempty(modelName)
                error('ModelStaticAnalysisService:InvalidInput', '模型名称不能为空');
            end
            
            if nargin < 3
                authorNames = getenv('username');
                if isempty(authorNames)
                    authorNames = 'Unknown';
                end
            end
            
            try
                fprintf('📄 正在生成SDD报告: %s\n', modelName);
                fprintf('   作者: %s\n', authorNames);
                
                % 基于规则第4条：调用独立的SDD报告生成工具函数
                % 根据环境添加CI参数
                if strcmpi(obj.environment, 'CI')
                    sddResult = genSDD(modelName, authorNames, 'CI');
                else
                    sddResult = genSDD(modelName, authorNames);
                end
                
                result.success = true;
                result.message = sddResult.Message;
                result.reportPath = obj.getSDDReportPath(modelName);
                
                fprintf('✅ SDD报告生成完成\n');
                
            catch ME
                result.success = false;
                result.message = sprintf('SDD报告生成失败: %s', ME.message);
                result.error = ME;
                % 使用格式化字符串避免result.message中的路径反斜杠被解释为转义字符
                error('ModelStaticAnalysisService:GenerateSDDFailed', '%s', result.message);
            end
        end
        
        %% ==================== Model Advisor配置管理 ====================
        
        function result = setDefaultConfiguration(obj)
            % 设置Model Advisor的默认配置
            % 输出：
            %   result - 包含成功标志和消息的结构体
            
            result = struct('success', false, 'message', '');
            
            try
                fprintf('⚙️ 正在设置Model Advisor默认配置...\n');
                
                % 基于规则第4条：调用独立的配置设置工具函数
                setDefaultMdlAdvCfg();
                
                result.success = true;
                result.message = 'Model Advisor默认配置已设置';
                
                fprintf('✅ Model Advisor配置设置完成\n');
                
            catch ME
                result.success = false;
                result.message = sprintf('设置Model Advisor配置失败: %s', ME.message);
                result.error = ME;
                % 使用格式化字符串避免result.message中的路径反斜杠被解释为转义字符
                error('ModelStaticAnalysisService:SetConfigFailed', '%s', result.message);
            end
        end
        
        function result = resetConfiguration(obj)
            % 重置Model Advisor配置到工厂设置
            % 输出：
            %   result - 包含成功标志和消息的结构体
            
            result = struct('success', false, 'message', '');
            
            try
                fprintf('⚙️ 正在重置Model Advisor配置...\n');
                
                % 基于规则第4条：调用独立的配置重置工具函数
                resetDefaultMdlAdvCfg();
                
                result.success = true;
                result.message = 'Model Advisor配置已重置到工厂设置';
                
                fprintf('✅ Model Advisor配置重置完成\n');
                
            catch ME
                result.success = false;
                result.message = sprintf('重置Model Advisor配置失败: %s', ME.message);
                result.error = ME;
                % 使用格式化字符串避免result.message中的路径反斜杠被解释为转义字符
                error('ModelStaticAnalysisService:ResetConfigFailed', '%s', result.message);
            end
        end
        
        %% ==================== 批量分析 ====================
        
        function results = runAllAnalysis(obj, modelName, varargin)
            % 运行所有模型静态分析（标准检查 + 指标计算 + SDD生成）
            % 输入：
            %   modelName - 模型名称
            %   varargin - 可选参数，传递给各个分析函数
            % 输出：
            %   results - 包含所有分析结果的结构体
            % 基于规则第2条和第6条：继续执行并收集所有错误，便于调试
            
            results = struct();
            results.modelName = modelName;
            results.startTime = datetime('now');
            results.analyses = struct();
            results.overallSuccess = true;
            
            if nargin < 2 || isempty(modelName)
                error('ModelStaticAnalysisService:InvalidInput', '模型名称不能为空');
            end
            
            fprintf('🚀 正在运行所有模型静态分析: %s\n', modelName);
            fprintf('═══════════════════════════════════════════\n');
            
            % 1. 模型标准检查
            fprintf('\n[1/3] 模型标准检查...\n');
            try
                results.analyses.standardsCheck = obj.checkStandards(modelName);
            catch ME
                results.analyses.standardsCheck = struct('success', false, ...
                    'message', sprintf('模型标准检查失败: %s', ME.message), ...
                    'error', ME);
                results.overallSuccess = false;
                fprintf('❌ 模型标准检查失败: %s\n', ME.message);
            end
            
            % 2. 模型指标计算
            fprintf('\n[2/3] 模型指标计算...\n');
            try
                results.analyses.metricsComputation = obj.computeMetrics(modelName, varargin{:});
            catch ME
                results.analyses.metricsComputation = struct('success', false, ...
                    'message', sprintf('模型指标计算失败: %s', ME.message), ...
                    'error', ME);
                results.overallSuccess = false;
                fprintf('❌ 模型指标计算失败: %s\n', ME.message);
            end
            
            % 3. SDD报告生成
            fprintf('\n[3/3] SDD报告生成...\n');
            try
                results.analyses.sddGeneration = obj.generateSDD(modelName);
            catch ME
                results.analyses.sddGeneration = struct('success', false, ...
                    'message', sprintf('SDD报告生成失败: %s', ME.message), ...
                    'error', ME);
                results.overallSuccess = false;
                fprintf('❌ SDD报告生成失败: %s\n', ME.message);
            end
            
            results.endTime = datetime('now');
            results.duration = results.endTime - results.startTime;
            
            fprintf('\n═══════════════════════════════════════════\n');
            if results.overallSuccess
                fprintf('✅ 所有模型静态分析完成！\n');
            else
                fprintf('⚠️  部分分析失败，请查看详细结果\n');
            end
            fprintf('总耗时: %s\n', char(results.duration));
            
            % 打印摘要
            obj.printAnalysisSummary(results);
        end
        
        %% ==================== 报告路径获取 ====================
        
        function path = getModelStandardsReportPath(obj, modelName)
            % 获取模型标准检查报告路径
            % 基于规则第3条：使用统一的 getRptPath 获取路径
            try
                path = getRptPath('model standards', modelName);
            catch ME
                % 基于规则第2条：明确报告错误，不使用silent fallback
                error('ModelStaticAnalysisService:GetPathFailed', ...
                    '无法获取模型标准检查报告路径: %s', ME.message);
            end
        end
        
        function path = getModelMetricsReportPath(obj, modelName)
            % 获取模型指标报告路径
            % 基于规则第3条：使用统一的 getRptPath 获取路径
            try
                path = getRptPath('model metrics', modelName);
            catch ME
                % 基于规则第2条：明确报告错误，不使用silent fallback
                error('ModelStaticAnalysisService:GetPathFailed', ...
                    '无法获取模型指标报告路径: %s', ME.message);
            end
        end
        
        function path = getSDDReportPath(obj, modelName)
            % 获取SDD报告路径
            % 基于规则第3条：使用统一的 getRptPath 获取路径
            try
                path = getRptPath('SDD report', modelName);
            catch ME
                % 基于规则第2条：明确报告错误，不使用silent fallback
                error('ModelStaticAnalysisService:GetPathFailed', ...
                    '无法获取SDD报告路径: %s', ME.message);
            end
        end
        
        function path = getDesignErrorReportPath(obj, modelName)
            % 获取设计错误检测报告路径
            % 基于规则第3条：使用统一的 getRptPath 获取路径
            try
                path = getRptPath('design error detection', modelName);
            catch ME
                % 基于规则第2条：明确报告错误，不使用silent fallback
                error('ModelStaticAnalysisService:GetPathFailed', ...
                    '无法获取设计错误检测报告路径: %s', ME.message);
            end
        end
        
        %% ==================== 辅助方法 ====================
        
        function printAnalysisSummary(obj, results)
            % 打印分析结果摘要
            % 输入：
            %   results - runAllAnalysis返回的结果结构体
            
            fprintf('\n📊 分析结果摘要\n');
            fprintf('═══════════════════════════════════════════\n');
            
            analysisNames = fieldnames(results.analyses);
            for i = 1:length(analysisNames)
                analysisName = analysisNames{i};
                analysisResult = results.analyses.(analysisName);
                
                % 格式化分析名称
                switch analysisName
                    case 'standardsCheck'
                        displayName = '模型标准检查';
                    case 'metricsComputation'
                        displayName = '模型指标计算';
                    case 'sddGeneration'
                        displayName = 'SDD报告生成';
                    otherwise
                        displayName = analysisName;
                end
                
                % 打印结果
                if analysisResult.success
                    fprintf('  ✅ %s: 成功\n', displayName);
                else
                    fprintf('  ❌ %s: 失败\n', displayName);
                end
            end
            
            fprintf('═══════════════════════════════════════════\n');
        end
    end
end

